package com.pisolution.scheduler.remote.utils;

import com.google.common.base.Preconditions;
import io.netty.channel.Channel;

import javax.annotation.Nullable;
import java.net.InetSocketAddress;

/**
 * 远程过程调用服务端地址信息.
 *
 * @author sora
 * @version 0.1.0
 */
public final class Host {
    /** 服务端IP地址. */
    private final String ip;

    /** 服务端端口信息. */
    private final int port;

    /** 服务端连接地址. */
    private final String address;

    // -------------------------------------------------------------------------------------------------
    //  初始化
    // -------------------------------------------------------------------------------------------------

    /**
     * 以给定的服务端地址与端口创建新的实例.
     *
     * @param ip 服务端地址.
     * @param port 服务端端口.
     */
    public Host(final String ip, final int port) {
        this.ip = ip;
        this.port = port;
        this.address = ip + ":" + port;
    }

    // -------------------------------------------------------------------------------------------------
    //  属性访问
    // -------------------------------------------------------------------------------------------------

    public String getIp() {
        return this.ip;
    }

    public int getPort() {
        return this.port;
    }

    public String getAddress() {
        return this.address;
    }

    // -------------------------------------------------------------------------------------------------
    //  辅助方法
    // -------------------------------------------------------------------------------------------------

    /**
     * 将给定的地址信息转换为具体的实例对象.
     *
     * @param address ip:port格式的地址信息.
     *
     * @return 转换后的 {@link Host} 实例.
     */
    public static Host of(@Nullable String address) {
        // 1. 校验地址信息是否非法.
        Preconditions.checkArgument(
            address != null && address.split(":").length == 2,
            String.format("The address %s provided is invalid.", address)
        );

        // 2. 尝试转换地址信息为具体实例.
        final String[] parts = address.split(":");

        return new Host(parts[0], Integer.parseInt(parts[1]));
    }

    /**
     * 将给定的 {@link Channel} 转换为 {@link Host}.
     *
     * @param channel 待转换的信道信息.
     *
     * @return 转换后的 {@link Host} 实例.
     */
    public static Host of(Channel channel) {
        // 1. 获取远程连接地址信息.
        final InetSocketAddress address = ((InetSocketAddress) channel.remoteAddress());

        // 2. 尝试转换.
        return new Host(address.getAddress().getHostAddress(), address.getPort());
    }
}
